package com.yupi.springbootinit.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yupi.springbootinit.annotation.AuthCheck;
import com.yupi.springbootinit.annotation.OperationLog;
import com.yupi.springbootinit.common.BaseResponse;
import com.yupi.springbootinit.common.DeleteRequest;
import com.yupi.springbootinit.common.ErrorCode;
import com.yupi.springbootinit.common.ResultUtils;
import com.yupi.springbootinit.constant.DepartmentConstants;
import com.yupi.springbootinit.constant.OrderType;
import com.yupi.springbootinit.constant.UserConstant;
import com.yupi.springbootinit.exception.BusinessException;
import com.yupi.springbootinit.exception.ThrowUtils;
import com.yupi.springbootinit.mapper.WorkflowTaskMapper;
import com.yupi.springbootinit.model.dto.salesorder.SalesOrderAddRequest;
import com.yupi.springbootinit.model.dto.salesorder.SalesOrderQueryRequest;
import com.yupi.springbootinit.model.dto.salesorder.SalesOrderUpdateRequest;
import com.yupi.springbootinit.model.entity.*;
import com.yupi.springbootinit.model.vo.CountItemVO;
import com.yupi.springbootinit.model.vo.SalesOrderVO;
import com.yupi.springbootinit.service.DepartmentService;
import com.yupi.springbootinit.service.SalesOrderService;
import com.yupi.springbootinit.service.UserService;
import com.yupi.springbootinit.service.WorkflowTaskService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 销售订单接口（优化版）
 */
@RestController
@RequestMapping("/salesOrder")
@Slf4j
public class SalesOrderController {

    @Resource
    private SalesOrderService salesOrderService;

    @Resource
    private UserService userService;

    @Resource
    private DepartmentService departmentService;

    @Resource
    private WorkflowTaskService workflowTaskService;

    private WorkflowTaskMapper workflowTaskMapper;

    // ==================== 创建订单 ====================

    /**
     * 创建订单（统一入口）
     * - 项目部（XM001）创建销售订单
     * - 工程部（GC001）创建研发订单
     * - 管理员可创建任意类型订单
     */
    @PostMapping("/add")
    @OperationLog(operation = "新增", module = "销售订单")
    public BaseResponse<Long> addOrder(@RequestBody SalesOrderAddRequest request,
                                       HttpServletRequest httpRequest) {
        if (request == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        // 获取登录用户
        User loginUser = userService.getLoginUser(httpRequest);

        // 构建订单主表
        SalesOrder salesOrder = new SalesOrder();
        BeanUtils.copyProperties(request, salesOrder);
        salesOrder.setDueDate(request.getDeliveryDate()); // DTO.deliveryDate -> entity.dueDate
        salesOrder.setCreatedBy(loginUser.getId());
        salesOrder.setCreatedByName(loginUser.getUserName());

        // 转换订单明细
        List<SalesOrderItem> items = convertToItems(request.getItems());

        // 根据用户部门确定订单类型
        OrderType orderType = determineOrderType(loginUser);

        // 创建订单
        Long orderId;
        if (orderType == OrderType.SALES) {
            orderId = salesOrderService.createSalesOrder(salesOrder, items);
        } else {
            orderId = salesOrderService.createRdoOrder(salesOrder, items);
        }

        // 创建工艺单待办（每个订单一个待办）
        SalesOrder createdOrder = salesOrderService.getById(orderId);
        createProcessSheetTask(createdOrder, loginUser);

        log.info("订单创建成功: 用户={}, 订单ID={}, 订单号={}, 类型={}",
                loginUser.getUserName(), orderId, createdOrder.getOrderNumber(), orderType.getName());

        return ResultUtils.success(orderId);
    }

    // ==================== 删除订单 ====================

    /**
     * 删除订单（仅管理员）
     */
    @PostMapping("/delete")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    @OperationLog(operation = "删除", module = "销售订单")
    public BaseResponse<Boolean> deleteOrder(@RequestBody DeleteRequest deleteRequest) {
        if (deleteRequest == null || deleteRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        long id = deleteRequest.getId();
        SalesOrder oldOrder = salesOrderService.getById(id);
        ThrowUtils.throwIf(oldOrder == null, ErrorCode.NOT_FOUND_ERROR, "订单不存在");

        boolean result = salesOrderService.removeById(id);
        log.info("订单删除成功: 订单ID={}, 订单号={}", id, oldOrder.getOrderNumber());

        return ResultUtils.success(result);
    }

    // ==================== 更新订单 ====================

    /**
     * 更新订单（管理员）
     */
    @PostMapping("/update")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    @OperationLog(operation = "修改", module = "销售订单")
    public BaseResponse<Boolean> updateOrder(@RequestBody SalesOrderUpdateRequest request,
                                             HttpServletRequest httpRequest) {
        if (request == null || request.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        log.info("管理员更新订单: 订单ID={}", request.getId());

        // 构建订单对象
        SalesOrder salesOrder = new SalesOrder();
        BeanUtils.copyProperties(request, salesOrder);
        salesOrder.setDueDate(request.getDeliveryDate());

        // 转换订单明细
        List<SalesOrderItem> items = convertToItems(request.getItems());

        // 更新订单（事务）
        boolean result = salesOrderService.updateOrderWithItems(
                request.getId(),
                salesOrder,
                items,
                request.getDeleteAttachmentIds());

        return ResultUtils.success(result);
    }

    /**
     * 编辑订单（普通用户按部门权限）
     */
    @PostMapping("/edit")
    @OperationLog(operation = "编辑", module = "销售订单")
    public BaseResponse<Boolean> editOrder(@RequestBody SalesOrderUpdateRequest request,
                                           HttpServletRequest httpRequest) {
        if (request == null || request.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        User loginUser = userService.getLoginUser(httpRequest);
        long orderId = request.getId();

        log.info("用户编辑订单: 用户={}, 订单ID={}", loginUser.getUserName(), orderId);

        // 权限检查
        SalesOrder oldOrder = salesOrderService.getById(orderId);
        if (oldOrder == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "订单不存在");
        }
        checkOrderPermission(loginUser, oldOrder, "编辑");

        // 构建订单对象
        SalesOrder salesOrder = new SalesOrder();
        BeanUtils.copyProperties(request, salesOrder);
        salesOrder.setDueDate(request.getDeliveryDate());
        salesOrder.setCreatedBy(loginUser.getId()); // 用于附件删除权限

        // 转换订单明细
        List<SalesOrderItem> items = convertToItems(request.getItems());

        // 更新订单（事务）
        boolean result = salesOrderService.updateOrderWithItems(
                orderId,
                salesOrder,
                items,
                request.getDeleteAttachmentIds());

        return ResultUtils.success(result);
    }

    // ==================== 查询订单 ====================

    /**
     * 根据ID获取订单
     */
    @GetMapping("/get")
    public BaseResponse<SalesOrderVO> getOrderById(long id, HttpServletRequest request) {
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        SalesOrder salesOrder = salesOrderService.getById(id);
        if (salesOrder == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "订单不存在，ID: " + id);
        }

        User loginUser = userService.getLoginUser(request);

        // 权限检查（管理员和PMC部门可查看所有订单）
        if (!userService.isAdmin(loginUser) && !isPmcDepartment(loginUser)) {
            checkOrderPermission(loginUser, salesOrder, "查看");
        }

        return ResultUtils.success(salesOrderService.getSalesOrderVO(salesOrder));
    }

    /**
     * 根据订单号获取订单
     */
    @GetMapping("/getByOrderNumber")
    public BaseResponse<SalesOrderVO> getOrderByOrderNumber(@RequestParam String orderNumber,
                                                            HttpServletRequest request) {
        if (orderNumber == null || orderNumber.trim().isEmpty()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        SalesOrder salesOrder = salesOrderService.getByOrderNumber(orderNumber);
        if (salesOrder == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "订单不存在");
        }

        User loginUser = userService.getLoginUser(request);

        // 权限检查（管理员和PMC部门可查看所有订单）
        if (!userService.isAdmin(loginUser) && !isPmcDepartment(loginUser)) {
            checkOrderPermission(loginUser, salesOrder, "查看");
        }

        return ResultUtils.success(salesOrderService.getSalesOrderVO(salesOrder));
    }

    /**
     * 分页获取订单列表（仅管理员）
     */
    @PostMapping("/list/page")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Page<SalesOrder>> listOrderByPage(@RequestBody SalesOrderQueryRequest request) {
        long current = request.getCurrent();
        long size = request.getPageSize();

        Page<SalesOrder> orderPage = salesOrderService.page(
                new Page<>(current, size),
                salesOrderService.getQueryWrapper(request));

        return ResultUtils.success(orderPage);
    }

    /**
     * 分页获取订单VO列表（按部门过滤）
     */
    @PostMapping("/list/page/vo")
    public BaseResponse<Page<SalesOrderVO>> listOrderVOByPage(@RequestBody SalesOrderQueryRequest request,
                                                              HttpServletRequest httpRequest) {
        long current = request.getCurrent();
        long size = request.getPageSize();
        ThrowUtils.throwIf(size > 50, ErrorCode.PARAMS_ERROR, "每页最多50条");

        User loginUser = userService.getLoginUser(httpRequest);

        // 构建查询条件
        QueryWrapper<SalesOrder> qw = salesOrderService.getQueryWrapper(request);

        // 非管理员：按部门过滤订单类型
        if (!userService.isAdmin(loginUser)) {
            Department dept = getDepartment(loginUser);
            String deptCode = dept.getDepartmentCode();

            // PMC部门可以查看所有订单
            if (!DepartmentConstants.PMC_DEPT.equals(deptCode)) {
                OrderType orderType = OrderType.fromDepartmentCode(deptCode);
                qw.eq("orderType", orderType.getCode());
            }
        }

        Page<SalesOrder> orderPage = salesOrderService.page(new Page<>(current, size), qw);
        return ResultUtils.success(salesOrderService.getSalesOrderVOPage(orderPage));
    }

    // ==================== 订单状态管理 ====================

    /**
     * 更新订单状态
     */
    @PostMapping("/updateStatus")
    @OperationLog(operation = "状态更新", module = "销售订单")
    public BaseResponse<Boolean> updateOrderStatus(@RequestParam Long orderId,
                                                   @RequestParam String newStatus,
                                                   @RequestParam(required = false) String currentNode,
                                                   @RequestParam(required = false) Double progress,
                                                   HttpServletRequest request) {
        if (orderId == null || newStatus == null || newStatus.trim().isEmpty()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        // 校验订单是否存在
        SalesOrder order = salesOrderService.getById(orderId);
        if (order == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "订单不存在");
        }

        // 权限检查
        User loginUser = userService.getLoginUser(request);
        checkOrderPermission(loginUser, order, "更新状态");

        boolean result = salesOrderService.updateOrderStatus(orderId, newStatus, currentNode, progress);
        return ResultUtils.success(result);
    }

    // ==================== 统计分析 ====================

    /**
     * 获取订单状态统计
     */
    @GetMapping("/statistics/status")
    public BaseResponse<List<CountItemVO>> getStatusStatistics(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);

        // 管理员：支持可选参数 orderType
        if (userService.isAdmin(loginUser)) {
            String ot = request.getParameter("orderType");
            if (ot == null || ot.isBlank() || "ALL".equalsIgnoreCase(ot)) {
                // 合并两类订单的统计
                return ResultUtils.success(mergeStatistics(
                        salesOrderService.getStatusStatistics(OrderType.SALES.getCode()),
                        salesOrderService.getStatusStatistics(OrderType.RDO.getCode())
                ));
            } else {
                OrderType orderType = OrderType.fromCode(ot.toUpperCase());
                return ResultUtils.success(salesOrderService.getStatusStatistics(orderType.getCode()));
            }
        }

        // 普通用户：按部门过滤
        Department dept = getDepartment(loginUser);
        OrderType orderType = OrderType.fromDepartmentCode(dept.getDepartmentCode());
        return ResultUtils.success(salesOrderService.getStatusStatistics(orderType.getCode()));
    }

    /**
     * 获取紧急程度统计
     */
    @GetMapping("/statistics/urgency")
    public BaseResponse<List<CountItemVO>> getUrgencyStatistics(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);

        // 管理员：支持可选参数 orderType
        if (userService.isAdmin(loginUser)) {
            String ot = request.getParameter("orderType");
            if (ot == null || ot.isBlank() || "ALL".equalsIgnoreCase(ot)) {
                // 合并两类订单的统计
                return ResultUtils.success(mergeStatistics(
                        salesOrderService.getUrgencyStatistics(OrderType.SALES.getCode()),
                        salesOrderService.getUrgencyStatistics(OrderType.RDO.getCode())
                ));
            } else {
                OrderType orderType = OrderType.fromCode(ot.toUpperCase());
                return ResultUtils.success(salesOrderService.getUrgencyStatistics(orderType.getCode()));
            }
        }

        // 普通用户：按部门过滤
        Department dept = getDepartment(loginUser);
        OrderType orderType = OrderType.fromDepartmentCode(dept.getDepartmentCode());
        return ResultUtils.success(salesOrderService.getUrgencyStatistics(orderType.getCode()));
    }

    /**
     * 获取即将到期的订单
     */
    @GetMapping("/upcoming")
    public BaseResponse<List<SalesOrderVO>> getUpcomingDeliveryOrders(
            @RequestParam(defaultValue = "7") Integer days,
            HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        Department dept = getDepartment(loginUser);
        OrderType orderType = OrderType.fromDepartmentCode(dept.getDepartmentCode());

        List<SalesOrderVO> orders = salesOrderService.getUpcomingDeliveryOrders(days, orderType.getCode());
        return ResultUtils.success(orders);
    }

    /**
     * 获取逾期订单
     */
    @GetMapping("/overdue")
    public BaseResponse<List<SalesOrderVO>> getOverdueOrders(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        Department dept = getDepartment(loginUser);
        OrderType orderType = OrderType.fromDepartmentCode(dept.getDepartmentCode());

        List<SalesOrderVO> orders = salesOrderService.getOverdueOrders(orderType.getCode());
        return ResultUtils.success(orders);
    }

    /**
     * 获取当前用户允许的订单类型
     */
    @GetMapping("/allowedType")
    public BaseResponse<String> getAllowedType(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);

        // 管理员返回 ALL
        if (userService.isAdmin(loginUser)) {
            return ResultUtils.success("ALL");
        }

        Department dept = getDepartment(loginUser);
        OrderType orderType = OrderType.fromDepartmentCode(dept.getDepartmentCode());
        return ResultUtils.success(orderType.getCode());
    }

    // ==================== 私有辅助方法 ====================

    /**
     * 转换订单明细DTO为实体
     */
    private List<SalesOrderItem> convertToItems(List<?> itemRequests) {
        if (itemRequests == null || itemRequests.isEmpty()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "订单明细不能为空");
        }

        return itemRequests.stream()
                .map(itemRequest -> {
                    SalesOrderItem item = new SalesOrderItem();
                    BeanUtils.copyProperties(itemRequest, item);
                    return item;
                })
                .collect(Collectors.toList());
    }

    /**
     * 根据用户部门确定订单类型
     */
    private OrderType determineOrderType(User user) {
        // 管理员：默认创建销售订单（或根据参数指定）
        if (userService.isAdmin(user)) {
            return OrderType.SALES;
        }

        Department dept = getDepartment(user);
        return OrderType.fromDepartmentCode(dept.getDepartmentCode());
    }

    /**
     * 创建工艺单待办（每个订单一个待办）
     */
    private void createProcessSheetTask(SalesOrder order, User creator) {
        // 使用第一个产品的名称作为待办任务描述
        String productName = salesOrderService.getFirstProductName(order.getId());

        workflowTaskService.createProcessSheetTaskForSalesOrder(
                order.getId(),
                order.getOrderNumber(),
                productName,
                creator.getId(),
                creator.getUserName()
        );

        log.info("创建工艺单待办: 订单号={}, 产品={}", order.getOrderNumber(), productName);
    }

    /**
     * 检查用户是否有权限操作订单
     */
    private void checkOrderPermission(User user, SalesOrder order, String operation) {
        // 1. 管理员有所有权限
        if (userService.isAdmin(user)) {
            return;
        }

        Department dept = getDepartment(user);
        String deptCode = dept.getDepartmentCode();
        String orderTypeCode = order.getOrderType();

        // 2. ✅ 项目部（销售部）：完全管理销售订单，不能查看研发订单
        if (DepartmentConstants.SALES_DEPT.equals(deptCode)) {
            if (OrderType.SALES.getCode().equals(orderTypeCode)) {
                return; // 允许所有操作
            } else {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "项目部无权查看研发订单");
            }
        }

        // 3. ✅ 工程部：完全管理研发订单，可查看所有销售订单（只读）
        if (DepartmentConstants.RD_DEPT.equals(deptCode)) {
            if (OrderType.RDO.getCode().equals(orderTypeCode)) {
                // 研发订单：完全权限
                log.info("✅ 工程部管理研发订单权限通过: userId={}, orderId={}, operation={}",
                        user.getId(), order.getId(), operation);
                return;
            } else if (OrderType.SALES.getCode().equals(orderTypeCode)) {
                // 销售订单：只读权限
                if (!"查看".equals(operation)) {
                    throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "工程部只能查看销售订单，不能" + operation);
                }
                log.info("✅ 工程部查看销售订单权限通过: userId={}, orderId={}",
                        user.getId(), order.getId());
                return;
            }
        }

        // 4. ✅ 其他执行部门（PMC、生产部、质检部）：基于任务的只读权限
        boolean isExecutionDept = DepartmentConstants.PMC_DEPT.equals(deptCode)
                || DepartmentConstants.PROD_DEPT.equals(deptCode)
                || DepartmentConstants.QA_DEPT.equals(deptCode);

        if (isExecutionDept) {
            // 只允许查看操作
            if (!"查看".equals(operation)) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "执行部门只能查看订单，不能" + operation);
            }

            // 检查是否有该订单的待办任务
            boolean hasRelatedTask = hasOrderRelatedTask(user.getId(), user.getDepartmentId(), order.getId());
            if (hasRelatedTask) {
                log.info("✅ 基于任务的权限检查通过: userId={}, deptCode={}, orderId={}",
                        user.getId(), deptCode, order.getId());
                return;
            }

            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "您没有该订单的相关任务，无权查看");
        }

        // 5. 其他部门：无权限
        throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无权" + operation + "该订单");
    }

    /**
     * ✅ 检查用户是否有订单相关的待办任务
     */
    private boolean hasOrderRelatedTask(Long userId, Long departmentId, Long orderId) {
        try {
            // 条件1：部门任务（未认领）
            QueryWrapper<WorkflowTask> deptTaskQuery = new QueryWrapper<>();
            deptTaskQuery.eq("bizType", "SALES_ORDER")
                    .eq("bizId", orderId)
                    .eq("departmentId", departmentId)
                    .eq("taskStatus", "PENDING")
                    .eq("isDelete", 0);

            // 条件2：用户任务（已认领）
            QueryWrapper<WorkflowTask> userTaskQuery = new QueryWrapper<>();
            userTaskQuery.eq("bizType", "SALES_ORDER")
                    .eq("bizId", orderId)
                    .eq("claimedBy", userId)
                    .in("taskStatus", Arrays.asList("IN_PROGRESS", "PENDING"))
                    .eq("isDelete", 0);

            Long deptTaskCount = workflowTaskMapper.selectCount(deptTaskQuery);
            Long userTaskCount = workflowTaskMapper.selectCount(userTaskQuery);

            boolean hasTask = (deptTaskCount + userTaskCount) > 0;

            log.info("订单任务权限检查: orderId={}, userId={}, deptId={}, deptTasks={}, userTasks={}, hasTask={}",
                    orderId, userId, departmentId, deptTaskCount, userTaskCount, hasTask);

            return hasTask;

        } catch (Exception e) {
            log.error("检查订单任务权限失败: orderId={}, userId={}", orderId, userId, e);
            return false;
        }
    }

    /**
     * 获取用户部门
     */
    private Department getDepartment(User user) {
        if (user.getDepartmentId() == null) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "缺少部门信息");
        }

        Department dept = departmentService.getById(user.getDepartmentId());
        if (dept == null) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "部门信息不存在");
        }

        return dept;
    }

    /**
     * 判断是否为PMC部门
     */
    private boolean isPmcDepartment(User user) {
        if (user.getDepartmentId() == null) {
            return false;
        }
        Department dept = departmentService.getById(user.getDepartmentId());
        return dept != null && DepartmentConstants.PMC_DEPT.equals(dept.getDepartmentCode());
    }

    /**
     * 合并统计数据
     */
    private List<CountItemVO> mergeStatistics(List<CountItemVO> list1, List<CountItemVO> list2) {
        java.util.Map<String, Long> map = new java.util.HashMap<>();

        for (CountItemVO item : list1) {
            map.put(item.getName(), map.getOrDefault(item.getName(), 0L) +
                    (item.getCount() == null ? 0L : item.getCount()));
        }
        for (CountItemVO item : list2) {
            map.put(item.getName(), map.getOrDefault(item.getName(), 0L) +
                    (item.getCount() == null ? 0L : item.getCount()));
        }

        return map.entrySet().stream()
                .map(entry -> new CountItemVO(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }
}